package com.edushare.common.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.query.SelectQuery;

import com.edushare.common.dao.academics.history.BatchEnrol;
import com.edushare.common.orm.ORMInterface;
import com.edushare.common.vo.AcademicYearModel;
import com.edushare.common.vo.Batches;
import com.edushare.common.vo.Curricula;
import com.edushare.common.vo.Departments;
import com.edushare.common.vo.Universities;
import com.edushare.common.vo.UserBatchLink;
import com.edushare.common.vo.Users;

public class BatchDAO extends CayenneBasedDAO {

	public BatchDAO(ORMInterface ormInterface) {
		super(ormInterface);
	}
	
	public Batches startNewBatch(Curricula curr, int semNo, int startingYear,
			AcademicYearModel startingSem) {
		Batches b = new Batches();
		b.setBatchStatus(Batches.BATCH_ACTIVE);
		b.setCurrentSemester(semNo);
		b.setCurricula(curr);
		b.setBatchYear(startingYear);
		b.setStartingSemester(startingSem);

		getDataContext().registerNewObject(b);
		getDataContext().commitChanges();
		return b;
	}

	public void endSemester(Batches b) {
		int semNum = b.getCurrentSemester();
		if (semNum < b.getCurricula().getTotalSemester() - 1) {
			b.setCurrentSemester(semNum + 1);
		} else {
			b.setBatchStatus(Batches.BATCH_GRADUATED);
		}
	}

	public int getCalendarYear(Batches b, int semNum) {
		if (!(semNum < b.getCurricula().getTotalSemester()))
			return 0;
		AcademicYearModelDAO aDAO = new AcademicYearModelDAO(ormInterface, b
				.getCurricula().getUniversity());
		int startingSem = b.getStartingSemester().getSequenceNo();
		int startingYear = b.getBatchYear();
		int endYear = startingYear + (semNum / aDAO.getNumberOfSemesters());
		int semRemainder = semNum % aDAO.getNumberOfSemesters();
		if (startingSem + semRemainder >= aDAO.getNumberOfSemesters()) {
			endYear++;
		}
		return endYear;
	}

	public AcademicYearModel getAcadYearModel(Batches b, int semNum) {
		if (!(semNum < b.getCurricula().getTotalSemester()))
			return null;
		AcademicYearModelDAO aDAO = new AcademicYearModelDAO(ormInterface, b
				.getCurricula().getUniversity());
		int semRemainder = semNum % aDAO.getNumberOfSemesters();
		int startSemSeqNum = b.getStartingSemester().getSequenceNo();
		int currSemSeqNum = startSemSeqNum + semRemainder;
		currSemSeqNum = currSemSeqNum % aDAO.getNumberOfSemesters();
		return aDAO.getSemester(currSemSeqNum);
	}

	@SuppressWarnings("unchecked")
	public Batches getBatchesById(int pk){
		Batches batch = null;
		Expression exp = Expression.fromString("batchId = $batchId");
		HashMap<String, Integer> params = new HashMap<String, Integer>();
		params.put("batchId", pk);
		SelectQuery query = new SelectQuery(Batches.class, exp
				.expWithParameters(params));
		List<Batches> lst = getDataContext().performQuery(query);
		if(lst!=null && lst.size() > 0)
			batch = (Batches)lst.get(0);
		return batch;		
	}

	public List<Batches> getAllBatches(Universities univ) {
		List<Curricula> currList = univ.getCurricula();
		List<Batches> batchList = new ArrayList<Batches>();
		for (Curricula c : currList) {
			batchList.addAll(c.getBatches());
		}
		return batchList;
	}
	
	public List<Batches> getAllBatches(Departments dept) {
		List<Curricula> cList = dept.getCurriculums();
		List<Batches> bList = new ArrayList<Batches>();
		for(Curricula c:cList){
			bList.addAll(c.getBatches());
		}
		return bList;
	}

	public boolean isStudentInBatch(Batches b, Users u) {
		return isUserInBatch(b, u, false);
		}

	public void addStudentsToBatch(Batches b, List<Users> users) {
		for (Users u : users) {
			addStudentToBatch(b, u);
		}
	}

	public void addStudentToBatch(Batches b, Users user) {
		addUserToBatch(b, user, false);
	}

	public List<Users> getUsers(Batches b) {
		List<Users> userList = new ArrayList<Users>();
		List<UserBatchLink> ubList = b.getUserBatchLink();
		for (UserBatchLink ub : ubList) {
			userList.add(ub.getUser());
		}
		return userList;
	}

	public void removeStudent(Batches b, Users u) {
		removeUser(u, b);
		}

	public List<Batches> getUserBatches(Users user){
		List<UserBatchLink> batchLink = user.getUserBatchLink();
		List<Batches> batch = new ArrayList<Batches>();
		for(UserBatchLink b:batchLink){
			batch.add(b.getBatch());
		}
		return batch;
	}
	
	public List<Curricula> getUserCurricula(Users user){
		List<UserBatchLink> batchLink = user.getUserBatchLink();
		List<Curricula> currs = new ArrayList<Curricula>();
		for(UserBatchLink b:batchLink){
			currs.add(b.getBatch().getCurricula());
		}
		return currs;
	}
	
	public void removeBatch(Batches b){
		if(b.getUserBatchLink().size() != 0)
			return;
		getDataContext().deleteObject(b);
		getDataContext().commitChanges();
	}

	public String addUserFB(Batches b, Users u){
		if(isStudentInBatch(b, u))
			return "User " + u.getCompleteUserName() + " already present in "
					+ b.getBatchName();
		else{
			addStudentToBatch(b, u);
			return "Added " + u.getCompleteUserName() + " to "
					+ b.getBatchName();
		}
	}	
	
	public void addUserToBatch(Batches b, Users u, boolean isFacad){
		if (isUserInBatch(b, u, true) || isUserInBatch(b, u, false))
			return;
		UserBatchLink ubLink = new UserBatchLink();
		ubLink.setBatch(b);
		ubLink.setFacad(isFacad);
		ubLink.setUser(u);
		getDataContext().registerNewObject(ubLink);
		new BatchEnrol(ormInterface).userBatchAddTasks(ubLink);
		getDataContext().commitChanges();
	}

	public boolean isUserInBatch(Batches b, Users u, boolean isFacad) {
		List<UserBatchLink> ubList = u.getUserBatchLink();
		for (UserBatchLink ub : ubList) {
			if (ub.getBatch() == b) {
				if (isFacad && ub.isFacad())
					return true;
				if (!isFacad && ub.isStudent())
					return true;
			}
		}
		return false;
	}
	
	public void removeUser(Users u, Batches b) {
		List<UserBatchLink> ubList = u.getUserBatchLink();
		UserBatchLink deleteLink = null;
		for (UserBatchLink ub : ubList) {
			if (ub.getBatch() == b)
				deleteLink = ub;
}
		if (deleteLink == null)
			return;
		getDataContext().deleteObject(deleteLink);
		getDataContext().commitChanges();
	}
}
